package com.espirit.view;

import static com.espirit.util.Constant.METHOD_COMPARE;
import static com.espirit.util.Constant.METHOD_UPDATE_PKG;
import static com.espirit.util.Constant.METHOD_UPLOAD;
import static com.espirit.util.Constant.CTX_SERVER;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.espirit.smc.CompareResult;
import com.espirit.smc.server.Server;
import com.espirit.util.CommonUtils;

public class ManagerServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private static final Logger logger = LoggerFactory.getLogger(ManagerServlet.class);

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String method = req.getParameter("method");
		req.setCharacterEncoding("UTF-8");
		resp.setCharacterEncoding("UTF-8");
		boolean isMultipart = ServletFileUpload.isMultipartContent(req);
		if (isMultipart && METHOD_UPLOAD.equals(method)) {
			doUpload(req, resp);
		} else if (METHOD_COMPARE.equals(method)) {
			doCompare(req, resp);
		} else if (METHOD_UPDATE_PKG.equals(method)) {
			doMakeUpdatePackage(req, resp);
		} else {
			resp.setContentType("text/html;charset=UTF-8");
			resp.setDateHeader("Date", Instant.now().toEpochMilli());
			resp.setStatus(HttpServletResponse.SC_OK);
			resp.getWriter().print("OK~~~~~~~~~~~");
		}
	}

	private void doUpload(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.reset();
		// Create a factory for disk-based file items
		DiskFileItemFactory factory = new DiskFileItemFactory();

		// Configure a repository (to ensure a secure temp location is used)
		ServletContext servletContext = this.getServletConfig().getServletContext();
		File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
		factory.setRepository(repository);

		FileSystem fs = FileSystems.getDefault();
		Path tempPath = fs.getPath(repository.getAbsolutePath(), "filelists");

		// Create a new file upload handler
		ServletFileUpload upload = new ServletFileUpload(factory);

		// Parse the request
		List<FileItem> items;
		resp.setContentType("text/html;charset=UTF-8");
		resp.setDateHeader("Date", Instant.now().toEpochMilli());
		try {
			if (!Files.exists(tempPath)) {
				Files.createDirectories(tempPath);
			}
			items = upload.parseRequest(req);
			String fileName;
			for (FileItem item : items) {
				fileName = item.getName();
				Path filePath = fs.getPath(tempPath.toAbsolutePath().toString(), fileName);
				item.write(filePath.toFile());
			}
			resp.setStatus(HttpServletResponse.SC_OK);
			resp.getWriter().println("Upload file list sucess!");
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			resp.getWriter().println("Upload file list failed!");
			throw new ServletException("Upload file failed!" + e.getMessage(), e);
		}
	}

	private void doCompare(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.reset();
		resp.setContentType("text/html;charset=UTF-8");
		resp.setDateHeader("Date", Instant.now().toEpochMilli());
		String fileName = req.getParameter("fileName");
		FileSystem fs = FileSystems.getDefault();
		ServletContext servletContext = this.getServletConfig().getServletContext();
		File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
		Path filePath = fs.getPath(repository.getAbsolutePath(), "filelists/" + fileName);
		if (!Files.exists(filePath)) {
			resp.getWriter().println("file not found ,please upload filelist first!");
			throw new ServletException("file not found ,please upload filelist first!");
		}

		Server server = (Server) servletContext.getAttribute(CTX_SERVER);
		try {
			List<CompareResult> results = server.loadDiffrentFileList(filePath);
			resp.setStatus(HttpServletResponse.SC_OK);
			if (results != null && !results.isEmpty()) {
				String json = CommonUtils.objectToJSON(results);
				resp.getWriter().print(new String(json.getBytes(),"UTF-8"));
			}else{
				resp.getWriter().print("[]");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			resp.getWriter().println("Load file differ failed!");
			throw new ServletException("Load file differ failed !" + e.getMessage(), e);
		}
	}

	
	private void doMakeUpdatePackage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.reset();
		resp.setContentType("text/html;charset=UTF-8");
		resp.setDateHeader("Date", Instant.now().toEpochMilli());
		String fileList = req.getParameter("fileList");
		ServletContext servletContext = this.getServletConfig().getServletContext();
		FileSystem fs = FileSystems.getDefault();
		File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
		Path packagesPath = fs.getPath(repository.getAbsolutePath(), "packages");
		Server server = (Server) servletContext.getAttribute(CTX_SERVER);
		try {
			Path pkgPath = server.makeUpdatePackage(fileList, packagesPath);
			if (pkgPath != null) {
				resp.setContentType("bin;charset=UTF-8");
				String fileName = pkgPath.getName(pkgPath.getNameCount()-1).toString();
				resp.setStatus(HttpServletResponse.SC_OK);
				resp.setHeader("Content-Disposition", "attachment; filename="+fileName);
				try (InputStream is = new FileInputStream(pkgPath.toFile());ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
					IOUtils.copy(is, bos);
					bos.writeTo(resp.getOutputStream());
				}
			}else{
				resp.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
				resp.getWriter().println("Load file differ failed !");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			resp.getWriter().println("Load file differ failed !");
			throw new ServletException("Load file differ failed !" + e.getMessage(), e);
		}

	}

}
